<?php

class SocketRedis
{
    private $socket;

    public function __construct(string $host, int $port = 6379)
    {
        $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        $res = socket_connect($socket, $host, $port);
        if (!$res) {
            throw new RuntimeException(sprintf('connect failed. err msg: %s', socket_last_error($socket)));
        }
        $this->socket = $socket;
    }

    private function getSocket()
    {
        return $this->socket;
    }

    public function execute(...$args)
    {
        $command = $this->processCommand(...$args);
        var_dump($command);
        $this->write($command);
        return $this->read();
    }

    private function write(string $command)
    {
        $socket = $this->getSocket();
        $length = strlen($command);
        $written = socket_write($socket, $command, $length);
        if ($length != $written) {
            return;
        }

        if ($written == false) {
            throw new RuntimeException(sprintf("write failed, err msg: %s \r\n", socket_last_error($socket)));
        }
    }

    private function read()
    {
        $socket = $this->getSocket();
        socket_recv($socket, $buf, 4096, 0);
        return $buf;
    }

    private function processResponse()
    {
    }

    /**
     * 处理参数
     */
    private function processCommand(...$args) : string
    {
        // *3\r\n$3\r\nSET\r\n$4\r\nname\r\n$3\r\nlqs\r\n;
        $commands[] = '*' . func_num_args();
        foreach($args as $arg) {array_push($commands, '$' . strlen($arg), $arg);}
        return implode("\r\n", $commands) . "\r\n";
    }

    public function __destruct()
    {
        if (!is_null($this->socket)) {
            socket_close($this->socket);
        }
    }
}

try {
    $cr = new SocketRedis('127.0.0.1', 6379);
    $result = $cr->execute("set", "name1", "lzy");
    $result = $cr->execute("set", "name2", "lqs");
} catch(\Exception $e)  {
    echo $e->getMessage();
}
